import * as THREE from 'three'
import { stats } from '../stats'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

function createCourse29 (dom: HTMLElement) {
  const scene = new THREE.Scene()

  const camera = new THREE.PerspectiveCamera(75, dom.offsetWidth / dom.offsetHeight, 0.01, 1000)
  camera.position.set(20, 20, 20)

  const render = new THREE.WebGLRenderer()
  render.setSize(dom.offsetWidth, dom.offsetHeight)
  render.shadowMap.enabled = true

  dom.appendChild(render.domElement)

  const axes = new THREE.AxesHelper(100)
  scene.add(axes)

  camera.position.x = -20
  camera.position.y = 250
  camera.position.z = 100
  camera.lookAt(scene.position)
  scene.add(camera)

  const controls = new OrbitControls(camera, render.domElement)
  controls.update()

  const cloud = createParticles()

  function createParticles () {
    const geom = new THREE.BufferGeometry()
    const material = new THREE.PointsMaterial({
      size: 4,
      transparent: true,
      opacity: 1.0,
      vertexColors: false,
      map: getTexture('https://dongli-three.oss-cn-shanghai.aliyuncs.com/raindrop.png'),
      blending: THREE.AdditiveBlending,
      depthWrite: false,
      sizeAttenuation: true,
      color: new THREE.Color(0xffffff)
    })

    const positions = []
    const colors = []
    const velocities = []

    const range = 500
    for (let i = 0; i < 15000; i++) {
      positions.push(Math.random() * range - range / 2,
        Math.random() * range - range / 2,
        Math.random() * range - range / 2)

      velocities.push((Math.random() - 0.5) / 3, 0.1 + Math.random() / 5)

      const color = new THREE.Color(0x00eeee)
      const asHSL: THREE.HSL = { h: 0, s: 0, l: 0 }
      color.getHSL(asHSL)
      color.setHSL(asHSL.h, asHSL.s, asHSL.l * Math.random())
      colors.push(color.r, color.g, color.b)
    }

    geom.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
    geom.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3))
    geom.setAttribute('velocity', new THREE.Float32BufferAttribute(velocities, 2))

    const cloud = new THREE.Points(geom, material)
    cloud.name = 'particles'
    scene.add(cloud)

    return cloud
  }

  function getTexture (strPNGPath: string) {
    const texture = new THREE.TextureLoader().load(strPNGPath)
    return texture
  }
  render.setAnimationLoop(anmation)

  function anmation () {
    stats.update()
    const posBufferAttr = cloud.geometry.getAttribute('position')
    const velBufferAttr = cloud.geometry.getAttribute('velocity')

    for (let i = 0; i < posBufferAttr.count; i++) {
      let posX = posBufferAttr.getX(i)
      let posY = posBufferAttr.getY(i)

      let velX = velBufferAttr.getX(i)
      const velY = velBufferAttr.getY(i)

      posX = posX - velX
      posY = posY - velY

      if (posX <= -20 || posX >= 20) velX = velX * -1
      if (posY <= 0) posY = 60

      posBufferAttr.setX(i, posX)
      posBufferAttr.setY(i, posY)
      velBufferAttr.setX(i, velX)
    }

    posBufferAttr.needsUpdate = true
    velBufferAttr.needsUpdate = true
    render.render(scene, camera)
  }

  return { camera, scene, render }
}

export {
  createCourse29
}
